﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace Objectware.Silverlight.Testing.Runner.Web.Services
{
	public enum TestRunStatus
	{
		Idle=1,
		Running,
		Stopped
	}

	public enum TestMethodResult
	{
		Passed=1,
		Inconclusive,
		Error
	}


	[DataContract]
	public class TestResult
	{
		public TestResult()
		{
			this.ResultTime = DateTime.Now;
		}

		[DataMember]
		public DateTime ResultTime;

		[DataMember]
		public string Type { get; set; }
		
		[DataMember]
		public string Method { get; set; }

		[DataMember]
		public string Message { get; set; }

		[DataMember]
		public string AdditionalInformation { get; set; }

		[DataMember]
		public TestMethodResult Result { get; set; }

	}

	[ServiceContract(Namespace = "")]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class TestResultService
	{
		private static TestRunStatus _Status = TestRunStatus.Idle;

		private static readonly List<TestResult>	_Results = new List<TestResult>();

		private object LoggingLockObject = new object();

		private void LogImpl(string format, params object[] parameters)
		{
			lock (LoggingLockObject)
			{
				File.AppendAllText("c:\\TestResultService"+this.GetHashCode()+".log", string.Format("{0}\n\r", string.Format(format, parameters)));
			}
		}

		[OperationContract]
		public void Ping()
		{
			
		}

		[OperationContract]
		public void Log(string message)
		{
			this.LogImpl(message);
			
		}

		
		[OperationContract]
		public void ReportResult(string type, string method, string message, string additionalInformation, TestMethodResult result)
		{
			Log("ReportResult()");
			_Results.Add(new TestResult
			                  	{
			                  		Type = type,
			                  		Method = method,
			                  		Message = message,
			                  		AdditionalInformation = additionalInformation,
			                  		Result = result
			                  	});
		}

		private IEnumerable<TestResult> GetTestResultQueryForMethod(string type, string method)
		{
			var query = from r in _Results
						where r.Type == type && r.Method == method
						select r;
			return query;
		}

		[OperationContract]
		public bool HasTestResultForMethod(string type, string method)
		{
			var query = this.GetTestResultQueryForMethod(type, method);
			var result = query.SingleOrDefault();
			return result != null;
		}

		[OperationContract]
		public TestResult GetTestResultForTestMethod(string type, string method)
		{
			var query = this.GetTestResultQueryForMethod(type, method);
			return query.SingleOrDefault();
		}
		
		[OperationContract]
		public TestResult[] GetAllResults()
		{
			return _Results.ToArray();
		}

		
		[OperationContract]
		public TestResult[]	GetResultsSinceGivenTime(DateTime time)
		{
			var query = from r in _Results
						where r.ResultTime >= time
			            select r;

			var results = query.ToArray();
			return results;
			
		}
		

		[OperationContract]
		public void BeginRun()
		{
			_Results.Clear();
			_Status = TestRunStatus.Running;
		}

		[OperationContract]
		public void EndRun()
		{
			_Status = TestRunStatus.Stopped;
		}

		
		[OperationContract]
		public TestRunStatus GetStatus()
		{
			return _Status;
		}
		
	}
}
